package dev.ideas.funkyj.sequence;

import dev.ideas.funkyj.function.F;
import dev.ideas.funkyj.function.F2;
import dev.ideas.funkyj.function.P;
import dev.ideas.funkyj.function.P2;
import dev.ideas.funkyj.support.Iterators;
import dev.ideas.funkyj.tuple.Pair;
import dev.ideas.funkyj.tuple.Trio;

import java.util.Iterator;

/**
*/
public class Sequence2<T1, T2> extends _Sequence<Pair<T1, T2>> {

    protected Sequence2(final Iterable<Pair<T1, T2>> iterable) {
        super(iterable);
    }

    protected Sequence2(final Iterable<T1> s1, final Iterable<T2> s2) {
        this(new Iterable<Pair<T1, T2>>() {
            public Iterator<Pair<T1, T2>> iterator() {
                return new Iterators.PairIterator<T1, T2>(s1.iterator(), s2.iterator());
            }
        });
    }

    @Override public Sequence2<T1, T2> where(P<? super Pair<T1, T2>> p) { return (Sequence2<T1, T2>) super.where(p); }

    public Sequence2<T1, T2> where1(final P<T1> p) {
        return where(new P2<T1, T2>() {
            @Override public boolean apply(T1 t1, T2 t2) {
                return p.apply(t1);
            }
        });
    }

    public Sequence2<T1, T2> where2(final P<T2> p) {
        return where(new P2<T1, T2>() {
            @Override public boolean apply(T1 t1, T2 t2) {
                return p.apply(t2);
            }
        });
    }

    //to flat
    public <T> Sequence<T> to(final F2<? super T1, ? super T2, T> f2) {
        return from(this).to(f2);
    }

    public <T3> Sequence3<T1, T2, T3> zip(final Iterable<T3> it3) {
        return new Sequence3<T1, T2, T3>(
                new Iterable<Trio<T1, T2, T3>>() {
                    public Iterator<Trio<T1, T2, T3>> iterator() {
                        return new Iterators.PairToTrioIterator<T1, T2, T3>(Sequence2.this, it3);
                    }
                }
        );
    }

    //todo can reuse super's?
    public Pair<T1, T2> first() {
        Iterator<Pair<T1, T2>> iterator = iterator(); //re-initiate
        return iterator.hasNext() ? iterator.next() : null;
    }

    //todo can reuse super's?
    public <T3> Sequence3<T1, T2, T3> zip(final T3... t3s) {
        return zip(from(t3s));
    }
}
